
#ifndef GOMOKU_CORE_STACK_STATE_H__
# define GOMOKU_CORE_STACK_STATE_H__

# include <gomoku/core/Gomoku.h>
# include <gomoku/core/State.h>

# include <map>
# include <list>

namespace gomoku
{

    class StateStack
    {
    public:
        enum Action
        {
            Push,
            Pop,
            Clear
        };

        StateStack();
        ~StateStack();

        void setContext(Context context);

        // T must be a subtype of gomoku::State
        template<typename T>
        void registerState(StateID stateID)
        {
            _states[stateID] = new T(*this, _context);
        }

        void handleEvent();
        void update(float dt);
        void draw();

        void pushState(StateID stateID);
        void popState();
        void clearStates();

        bool isEmpty() const; // loop game

    private:
        struct PendingChange
        {
            Action action;
            StateID stateID;
        };

        void applyPendingChanges();

    private:
        Context _context;
        std::map<StateID, State *> _states;

        std::list<State *> _currents; // current state who running,
        std::list<PendingChange> _pendingList; // next states to run;
    };
}

#endif  // GOMOKU_CORE_STACK_STATE_H__
